﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace DDASProject.ExtentLib
{
    public partial class FieldControl : TextBox
    {

        private int _fieldIndex = -1;
        private byte _rangeLower; // = MinimumValue;  // this is removed for FxCop approval
        private byte _rangeUpper = MaximumValue;

        //private TextFormatFlags _textFormatFlags = TextFormatFlags.HorizontalCenter |
        //   TextFormatFlags.SingleLine | TextFormatFlags.NoPadding;

        public const byte MinimumValue = 0;
        public const byte MaximumValue = 255;
        public event EventHandler<CedeFocusEventArgs> CedeFocusEvent;
        public event EventHandler<TextChangedEventArgs> TextChangedEvent;

        public bool Blank
        {
            get { return (TextLength == 0); }
        }

        public int FieldIndex
        {
            get { return _fieldIndex; }
            set { _fieldIndex = value; }
        }


        public byte RangeLower
        {
            get { return _rangeLower; }
            set
            {
                if (value < MinimumValue)
                {
                    _rangeLower = MinimumValue;
                }
                else if (value > _rangeUpper)
                {
                    _rangeLower = _rangeUpper;
                }
                else
                {
                    _rangeLower = value;
                }

                if (Value < _rangeLower)
                {
                    Text = _rangeLower.ToString();
                }
            }
        }

        public byte RangeUpper
        {
            get { return _rangeUpper; }
            set
            {
                if (value < _rangeLower)
                {
                    _rangeUpper = _rangeLower;
                }
                else if (value > MaximumValue)
                {
                    _rangeUpper = MaximumValue;
                }
                else
                {
                    _rangeUpper = value;
                }

                if (Value > _rangeUpper)
                {
                    Text = _rangeUpper.ToString();
                }
            }
        }

        public byte Value
        {
            get
            {
                byte result = 0;
                try
                {
                    result = Byte.Parse(Text);
                }
                catch 
                {
                    result = RangeLower;
                }               
               
                return result;
            }
        }

        public  Size MinimumSize
        {
            get
            {              
                return new Size(10,10);
            }
        }


        public FieldControl()
        {
            InitializeComponent();
            BorderStyle = BorderStyle.None;
            MaxLength = 3;
            Size = MinimumSize;
            TabStop = false;
            TextAlign = HorizontalAlignment.Center;
            base.Text = Text;
        }

        public void Clear()
        {
            Text = string.Empty;
        }
        protected override void OnPaint(PaintEventArgs pe)
        {
            // TODO: 在此处添加自定义绘制代码
            
            // Calling the base class OnPaint
            base.OnPaint(pe);
        }

#region 方法
        public void TakeFocus(Action action)
        {
            Focus();

            switch (action)
            {
                case Action.Trim:

                    if (TextLength > 0)
                    {
                        int newLength = TextLength - 1;
                        base.Text = Text.Substring(0, newLength);
                    }

                    SelectionStart = TextLength;

                    return;

                case Action.Home:

                    SelectionStart = 0;
                    SelectionLength = 0;

                    return;

                case Action.End:

                    SelectionStart = TextLength;

                    return;
            }
        }

        public void TakeFocus(Direction direction, Selection selection)
        {
            Focus();

            if (selection == Selection.All)
            {
                SelectionStart = 0;
                SelectionLength = TextLength;
            }
            else
            {
                SelectionStart = (direction == Direction.Forward) ? 0 : TextLength;
            }
        }
 
        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (null == e) { throw new ArgumentNullException("e"); }

            base.OnKeyDown(e);

            switch (e.KeyCode)
            {
                case Keys.Home:
                    SendCedeFocusEvent(Action.Home);
                    return;

                case Keys.End:
                    SendCedeFocusEvent(Action.End);
                    return;
            }

            if (IsCedeFocusKey(e))
            {
                SendCedeFocusEvent(Direction.Forward, Selection.All);
                e.Handled = true;
                return;
            }
            else if (IsForwardKey(e))
            {
                if (e.Control)
                {
                    SendCedeFocusEvent(Direction.Forward, Selection.All);
                    return;
                }
                else if (SelectionLength == 0 && SelectionStart == TextLength)
                {
                    SendCedeFocusEvent(Direction.Forward, Selection.None);
                    return;
                }
            }
            else if (IsReverseKey(e))
            {
                if (e.Control)
                {
                    SendCedeFocusEvent(Direction.Reverse, Selection.All);
                    return;
                }
                else if (SelectionLength == 0 && SelectionStart == 0)
                {
                    SendCedeFocusEvent(Direction.Reverse, Selection.None);
                    return;
                }
            }
            else if (IsBackspaceKey(e))
            {
                HandleBackspaceKey(e);
            }
            else if (!IsNumericKey(e) &&
                      !IsEditKey(e) &&
                      !IsEnterKey(e))
            {
                e.Handled = true;
            }
        }
        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);

            if (!Blank)
            {
                int value = 0;

                try
                {
                    value = Byte.Parse(Text);
                    if (value > RangeUpper)
                    {
                        base.Text = RangeUpper.ToString();
                        SelectionStart = 0;
                    }
                    else if ((TextLength == MaxLength) && (value < RangeLower))
                    {
                        base.Text = RangeLower.ToString();
                        SelectionStart = 0;
                    }
                    else
                    {
                        int originalLength = TextLength;
                        int newSelectionStart = SelectionStart;

                        base.Text = value.ToString();

                        if (TextLength < originalLength)
                        {
                            newSelectionStart -= (originalLength - TextLength);
                            SelectionStart = Math.Max(0, newSelectionStart);
                        }
                    }
                }
                catch 
                {
                    base.Text = "0";
                }               
            }

            if (null != TextChangedEvent)
            {
                TextChangedEventArgs args = new TextChangedEventArgs();
                args.FieldIndex = FieldIndex;
                args.Text = Text;
                TextChangedEvent(this, args);
            }

            if (TextLength == MaxLength && Focused && SelectionStart == TextLength)
            {
                SendCedeFocusEvent(Direction.Forward, Selection.All);
            }
        }

 

#endregion // Protected Methods

        #region Private Methods

        private void HandleBackspaceKey(KeyEventArgs e)
        {
            if (!ReadOnly && (TextLength == 0 || (SelectionStart == 0 && SelectionLength == 0)))
            {
                SendCedeFocusEvent(Action.Trim);
                e.Handled = true;
                
            }
        }

        private static bool IsBackspaceKey(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Back)
            {
                return true;
            }

            return false;
        }

        private bool IsCedeFocusKey(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Decimal ||
                 e.KeyCode == Keys.Space)
            {
                if (TextLength != 0 && SelectionLength == 0 && SelectionStart != 0)
                {
                    return true;
                }
            }

            return false;
        }

        private static bool IsEditKey(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Back ||
                 e.KeyCode == Keys.Delete)
            {
                return true;
            }
            else if (e.Modifiers == Keys.Control &&
                      (e.KeyCode == Keys.C ||
                        e.KeyCode == Keys.V ||
                        e.KeyCode == Keys.X))
            {
                return true;
            }

            return false;
        }

        private static bool IsEnterKey(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter ||
                 e.KeyCode == Keys.Return)
            {
                return true;
            }

            return false;
        }

        private static bool IsForwardKey(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Right ||
                 e.KeyCode == Keys.Down)
            {
                return true;
            }

            return false;
        }

        private static bool IsNumericKey(KeyEventArgs e)
        {
            if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
            {
                if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
                {
                    return false;
                }
            }

            return true;
        }

        private static bool IsReverseKey(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Left ||
                 e.KeyCode == Keys.Up)
            {
                return true;
            }

            return false;
        }

        private void SendCedeFocusEvent(Action action)
        {
            if (null != CedeFocusEvent)
            {
                CedeFocusEventArgs args = new CedeFocusEventArgs();
                args.FieldIndex = FieldIndex;
                args.Action = action;
                CedeFocusEvent(this, args);
            }
        }

        private void SendCedeFocusEvent(Direction direction, Selection selection)
        {
            if (null != CedeFocusEvent)
            {
                CedeFocusEventArgs args = new CedeFocusEventArgs();
                args.FieldIndex = FieldIndex;
                args.Action = Action.None;
                args.Direction = direction;
                args.Selection = selection;
                CedeFocusEvent(this, args);
            }
        }
#endregion
    }
    public enum Direction
    {
        Forward,
        Reverse
    }

    public enum Selection
    {
        None,
        All
    }

    public enum Action
    {
        None,
        Trim,
        Home,
        End
    }

    public class CedeFocusEventArgs : EventArgs
    {
        private int _fieldIndex;
        private Action _action;
        private Direction _direction;
        private Selection _selection;

        public int FieldIndex
        {
            get { return _fieldIndex; }
            set { _fieldIndex = value; }
        }

        public Action Action
        {
            get { return _action; }
            set { _action = value; }
        }

        public Direction Direction
        {
            get { return _direction; }
            set { _direction = value; }
        }

        public Selection Selection
        {
            get { return _selection; }
            set { _selection = value; }
        }
    }

    public class TextChangedEventArgs : EventArgs
    {
        private int _fieldIndex;
        private String _text;

        public int FieldIndex
        {
            get { return _fieldIndex; }
            set { _fieldIndex = value; }
        }

        public String Text
        {
            get { return _text; }
            set { _text = value; }
        }
    }

}
